hhkb
웹 개발

블로그_06_에디터 기능 개선 및 버그 수정

작성자 : Heehyeon Yoo|2025-12-19
# Blog# BlockNote# 에디터# Troubleshooting# Refactoring

에디터 안정화: 험난한 기능 개선의 길

지난번 BlockNote 도입으로 큰 틀은 잡혔지만, 실제로 사용해보니 디테일한 부분에서 여전히 많은 문제가 있었다.
오늘은 이 문제들을 하나씩 해결하며 에디터의 완성도를 높이는 데 집중했다.

1. 이미지 로딩과 NBSP의 충돌

가장 골치 아팠던 문제는 에디터에서 이미지가 로드되지 않는 현상이었다.
원인을 파헤쳐보니 마크다운을 BlockNote 블록으로 변환하는 전처리 과정(markdownToBlocks)에서 문제가 있었다.
BlockNote가 빈 줄을 제대로 인식하지 못해서 모든 빈 줄을 NBSP(\u00A0)로 변환하도록 처리했었는데,
이 과정에서 이미지 문법 바로 앞뒤의 줄바꿈까지 NBSP로 변해버리면서 파서가 이미지를 인식하지 못하게 된 것이다.

결국 전처리 로직을 수정하여 '이미지가 아닌 빈 줄'만 선별적으로 변환하려 했으나 정규식 처리가 까다로웠고,
근본적으로는 저장 시점에 처리하는 것이 맞다고 판단했다.
불필요한 전처리를 걷어내고 저장 로직(blocksToMarkdown)을 강화하는 방향으로 선회하여 깔끔하게 해결했다.

2. IDE 스타일 저장: 라인별 편집의 로망

보통의 웹 에디터는 블록 단위로 생각하고 저장한다. 문단과 문단 사이는 당연히 떨어져 있어야 한다는 식이다.
하지만 나는 VS Code에서 마크다운 파일을 열고 한 줄 한 줄 코드를 짜듯이 글을 쓰는 경험을 웹에서도 원했다.

BlockNote는 기본적으로 모든 블록 사이에 \n\n을 넣어 저장한다.
이게 마크다운 표준에는 맞지만, IDE에서 볼 때는 불필요하게 줄 간격이 넓어 보여 가독성을 해쳤다.
내가 입력한 빈 줄만 저장되고, 나머지는 붙여서 저장되는 진정한 IDE 스타일을 구현하고 싶었다.

이를 위해 마커(Marker) 방식을 도입했다.

  1. 저장 전, 에디터상의 진짜 빈 줄(NBSP 블록)을 __EMPTY_LINE__이라는 마커로 변환한다.
  2. 모든 \n\n\n으로 바꿔버린다. (모든 블록을 다닥다닥 붙임)
  3. 마지막으로 __EMPTY_LINE__ 마커를 다시 \n으로 복원한다.

결과는 만족스러웠다. 웹 에디터에서 작성한 글을 VS Code로 열어도 이질감이 전혀 없었다.
내가 의도적으로 띄운 줄만 정확히 빈 줄로 남고, 나머지는 깔끔하게 정리되어 있었다.
'웹에서도 IDE처럼 라인 단위로 편집한다'는 의도가 기술적으로 구현된 순간이었다.
덤으로, 리스트 아이템 사이나 헤딩과 본문 사이에 강제로 들어가는 공백도 제거하여 훨씬 밀도 있는 문서 작성이 가능해졌다.

3. URL 한글 깨짐과 링크 처리

마크다운으로 저장될 때 한글 URL이 %ED%85%8C... 처럼 인코딩되어 저장되는 문제가 있었다. 가독성도 떨어지고 링크 수정도 불편했다.
저장 로직에 decodeURIComponent를 추가하여 한글이 그대로 저장되도록 수정했다.
또한 공백이 포함된 파일명이나 URL(예: Program Files)은 마크다운 파싱 오류를 일으킬 수 있어,
이런 경우에만 자동으로 < > 기호로 감싸주는([link](<url with space>)) 로직도 추가했다.

4. 다크모드 동기화: 내 맘대로 안 되는 브라우저

앱은 라이트모드인데 에디터만 다크모드로 나오는 기이한 현상이 있었다.
알고 보니 prefers-color-scheme 미디어 쿼리 때문에 브라우저/OS 설정이 강제로 적용되고 있었다.
라이브러리 내장 CSS를 오버라이드하고, 테마 감지 로직에서도 브라우저 설정을 무시하고 오직 **앱의 테마 상태(html.dark 클래스)**만 따르도록 변경했다.
이제 시스템 설정과 무관하게 웹사이트 설정대로 에디터 테마가 완벽하게 동기화된다.

더 나은 경험을 위한 UI/UX 디테일링

에디터 코어 기능 외에도 글쓰는 경험을 쾌적하게 만들기 위해 놓치고 있던 디테일들을 함께 손봤다.

  • TOC/아웃라인 디자인 통일: 뷰 모드와 에디터의 목차 디자인을 통일했다. 아이콘, 포인트 컬러, 헤딩 카운트 배지까지 맞춰서 일관성을 높였고, 본문 제목(article-title)이 목차에 중복으로 뜨는 문제도 ID 필터링으로 해결했다.
  • 직관적인 태그 관리: 태그를 클릭해야 삭제되는 방식에서, 마우스를 올리면 ✕ 삭제 표시가 뜨도록 변경했다. 또한 무분별한 태그 입력을 막기 위해 최대 5개까지만 입력 가능하도록 제한을 두었다.
  • 날짜 선택 UI: 기존 문자열 입력 방식에서 Date Picker를 도입해 클릭 한 번으로 날짜를 변경할 수 있게 했다. 날짜 포맷도 문서 전체적으로 통일했다.
  • WYSIWYG 강화: 편집기 내 H2 구분선 제거, 불필요한 공백 제거, 그리고 단일 엔터도 줄바꿈으로 인식하도록(remark-breaks) 처리하여 "보이는 대로 저장되고 보이는 대로 출력되는" 경험을 완성했다.